package com.huitone.smspfm.task;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;

import com.bin.common.utils.StringUtils;
import com.huitone.smspfm.logger.ExtLogger;
import com.huitone.smspfm.core.config.AppStaticConfigs;
import com.huitone.smspfm.core.waterpipe.client.IGateLink;
import com.huitone.smspfm.core.waterpipe.client.impl.SimpleGateLink;

/**   
* @Title: RouteFaultCheckTask.java 
* @Package com.huitone.smspfm.module 
* @Description: 检测路由是否故障，以及故障后未处理数据的后续流程  
* @author 
* @date 
* @version V1.0   
*/
public class RouteFaultCheckTask extends Thread {

	private static ExtLogger logger = ExtLogger.create(RouteFaultCheckTask.class);
	
	private static Map<String, IGateLink> faultGateLinks = new HashMap<String, IGateLink>();
	
	//3*60*1000
	private long excuteInterval = 100;
	
	private long numCnt = 0;
	private boolean keepGoing = true;
	
	@Override
	public void run() {
		
		while(isKeepGoing() && !this.isInterrupted()) {
			
			try{
			if (numCnt == 0) {
				// 3*60*1000
				// 检查 网关是否出错
				Map<String, IGateLink> tempGateLink = AppStaticConfigs.simpleGateLinkRegister
						.getGateLinks();
				for (String key : tempGateLink.keySet()) {
					IGateLink igateLink = tempGateLink.get(key);
					if (igateLink instanceof SimpleGateLink) {
						SimpleGateLink simpleGateLink = (SimpleGateLink) igateLink;
						if (!StringUtils.equals("1", simpleGateLink
								.getGateDef().getFaultStatus())) {
							faultGateLinks.put(key, simpleGateLink);
						} else {
							if (faultGateLinks.containsKey(key)) {
								faultGateLinks.remove(key);
							}
						}

					}
				}
			}
			
			
			//100ms
			faultGateHandler();
			
			numCnt++;
			if(numCnt*excuteInterval >= 3*60*1000){
				numCnt = 0;
			}
			}catch (Exception e){}
			
			
			try {
				Thread.sleep(excuteInterval);
			} catch (InterruptedException e) {}
		}
		
	}
	
	@SuppressWarnings("rawtypes")
	protected void faultGateHandler() {
		// TODO Auto-generated method stub
		if(faultGateLinks.size() <= 0){
			return;
		}
		RedisScript<List> scriptGetName = new DefaultRedisScript<List>(AppStaticConfigs.luaGetPriListName, List.class);
//		RedisScript<List> scriptGetLength = new DefaultRedisScript<List>(AppStaticConfigs.luaGetFriListName, List.class);
//		RedisScript<Long> scriptTransferPriList = new DefaultRedisScript<Long>(AppStaticConfigs.luaTransferPriList, List.class);
		RedisScript<Long> scriptTransferPriList = new DefaultRedisScript<Long>(AppStaticConfigs.luaTransferPriList, Long.class);
		for(String key : faultGateLinks.keySet()){
			IGateLink igateLink = faultGateLinks.get(key);
			SimpleGateLink simpleGateLink = null;
			if(igateLink instanceof SimpleGateLink){
				simpleGateLink = (SimpleGateLink) igateLink;
				
			}
			if(simpleGateLink == null){
				continue;
			}
			String redisKey = AppStaticConfigs.iSMPriListNamesSet;
			Set<String> priListNames = new HashSet<String>();
			
			List<String> keys = new ArrayList<>();
			keys.add(redisKey);
			List<String> entities = AppStaticConfigs.scriptOpts.getList(scriptGetName, keys, 1000+"");
			
			if(entities != null && entities.size() > 0){ 
				for(int i  = 0; i < entities.size() ; i++ ){
					String priListName = entities.get(i);
					String gateIdKey = StringUtils.splitThRIndex(priListName, ":", 1);
					if(!StringUtils.equals(key, gateIdKey)){
						continue;
					}
					priListNames.add(entities.get(i));
				}
			}
			
			if(priListNames == null || priListNames.size() <= 0){
				continue;
			}
			
			//检查key 下是否有虚通道
			boolean virtuaFlag = AppStaticConfigs.virtualGateLinkIdMap.containsKey(key);
			String linkId = "";
			Long linkIdLength = 0L;
			if(virtuaFlag){
				 Set<String> set = AppStaticConfigs.virtualGateLinkIdMap.get(key);
				 for(String id : set){
					 
					 IGateLink virtuaIgateLink =  AppStaticConfigs.simpleGateLinkRegister.get(id);
					 SimpleGateLink virtuaSimleGateLink = null;
					 if(virtuaIgateLink instanceof SimpleGateLink){
						 virtuaSimleGateLink = (SimpleGateLink) virtuaIgateLink;
					 }
					 //虚通道是否可用
					 if(virtuaSimleGateLink == null || 
							 ! StringUtils.equals("1",virtuaSimleGateLink.getGateDef().getFaultStatus())){
						 continue;
					 }
					 
					 
//					 String redisVirtuaKey = "SM:"+id+":Pri:*";
					 String redisVirtuaKey = "SM:"+id+":Cache:*";
					 List<String> tempkeys = new ArrayList<>();
					 tempkeys.add(redisVirtuaKey);
					 List<String> entities1 = AppStaticConfigs.scriptOpts.getList(scriptGetName, tempkeys, 1000 +"");
					 //获取网关长度
					 Long length = 0L;
					 if(entities1 != null && entities1.size() > 0){
						 for(int i = 0; i < entities1.size(); i++){
							 Long tL = GetPriListLengthTask.priListLength.get(entities1.get(i));
							 if(tL != null){
								 length += tL;
							 }
						 }
					 }
					 
					 if(linkIdLength == 0L){
						 linkIdLength = length;
						 linkId = id;
					 } else {
						 if(length < linkIdLength){
							 linkIdLength = length;
							 linkId = id;
						 }
					 }
				 
				 }
			}
			
			if(linkId == null){
				continue;
			}
			
			
			for(String oldpriName : priListNames){
				String newPriName = reviseLinkId(oldpriName,linkId,2);
				List<String> tempKeys = new ArrayList<String>();
				tempKeys.add(oldpriName);
				tempKeys.add(newPriName);
				long count = 1000L;
				
				while(count != 0){
					//复制队列数据到新的通道中去处理
					count = AppStaticConfigs.scriptOpts.execute(scriptTransferPriList, tempKeys, 1000+"");
					logger.debug("通道队列复制：  src: "+oldpriName +"  des: "+newPriName +"  数量: "+count);
				}
			}	
		}
	}

	private String reviseLinkId(String oldpriName, String regx,int mark) {
		StringBuffer result = new StringBuffer();
		List<String> list = StringUtils.splitToList(oldpriName, ":");
		if(list != null && list.size() >= mark){
			for (int i = 0 ; i < list.size() ; i ++){
				
				if(i != 0){
					result.append(":");
				}
				if((i+1 == mark)){
					result.append(regx);
				} else {
					result.append(list.get(i));
				}
			}	
		}
		return result.toString();
	}

	public boolean isKeepGoing() {
		return keepGoing;
	}

	public void setKeepGoing(boolean keepGoing) {
		this.keepGoing = keepGoing;
	}

	@Override
	public void destroy() {
		this.setKeepGoing(false);
		this.interrupt();
	}
}
